﻿using FluentParser.Expressions;
using Microsoft.VisualStudio.TestTools.UnitTesting;

namespace FluentParser.Tests.Expressions.Rules.Composition
{
    [TestClass]
    public class GreedyChoiceExpressionRuleTests
    {
        [TestMethod]
        public void Parse_WhenBothSucceed_ShouldReturnSecond()
        {
            Symbol left = "Some";
            Symbol right = "SomeText";
            Expr<string> expr = left.Cast<string>() & right.Cast<string>();
            var result = expr.Parse("SomeTextMatchingBothExpressions");

            string expected = "SomeText";
            string actual = result.Value;

            Assert.AreEqual(expected, actual);
        }

        [TestMethod]
        public void Parse_WhenFirstSucceedAndSecondFails_ShouldReturnFirst()
        {
            Symbol left = "Some";
            Symbol right = "SomeInvalidText";
            Expr<string> expr = left.Cast<string>() & right.Cast<string>();
            var result = expr.Parse("SomeTextMatchingOnlyFirstExpression");

            string expected = "Some";
            string actual = result.Value;

            Assert.AreEqual(expected, actual);
        }

        [TestMethod]
        public void Parse_WhenFirstFails_ShouldFailAndNeverAttemptSecond()
        {
            Symbol left = "SomeInvalidText";
            Symbol right = "Some";
            Expr<string> expr = left.Cast<string>() & right.Cast<string>();

            ParsingResult<string> expected = null;
            ParsingResult<string> actual = expr.Parse("SomeTextMatchingOnlySecondExpression");

            Assert.AreEqual(expected, actual);
        }

        [TestMethod]
        public void ParseNode_WhenBothSucceed_ShouldReturnSecond()
        {
            Symbol left = "Some";
            Symbol right = "SomeText";
            Expr<string> expr = left.Cast<string>() & right.Cast<string>();
            var result = expr.ParseNode("SomeTextMatchingBothExpressions");

            string expected = "SomeText";
            string actual = result.Value as string;

            Assert.AreEqual(expected, actual);
        }

        [TestMethod]
        public void ParseNode_WhenFirstSucceedAndSecondFails_ShouldReturnFirst()
        {
            Symbol left = "Some";
            Symbol right = "SomeInvalidText";
            Expr<string> expr = left.Cast<string>() & right.Cast<string>();
            var result = expr.ParseNode("SomeTextMatchingOnlyFirstExpression");

            string expected = "Some";
            string actual = result.Value as string;

            Assert.AreEqual(expected, actual);
        }

        [TestMethod]
        public void ParseNode_WhenFirstFails_ShouldFailAndNeverAttemptSecond()
        {
            Symbol left = "SomeInvalidText";
            Symbol right = "Some";
            Expr<string> expr = left.Cast<string>() & right.Cast<string>();
            ParsingNodeResult result = expr.ParseNode("SomeTextMatchingOnlySecondExpression");

            Assert.IsFalse(result.IsSuccess);

            result.AssertChildren(
                false);
        }
    }
}
